use std::fmt::{Show, Formatter};
use std::fmt;
use std::io::fs;
+use glob::Pattern;
use core::{Package, PackageId, Summary, SourceId, Source, Dependency, Registry};
use ops;
/// are relevant for building this package, but it also contains logic to
/// use other methods like .gitignore to filter the list of files.
pub fn list_files(&self, pkg: &Package) -> CargoResult<Vec<Path>> {
- // TODO: add an `excludes` section to the manifest which is another way
- // to filter files out of this set that is returned.
- return if self.path.join(".git").exists() {
+ let candidates = try!(if self.path.join(".git").exists() {
self.list_files_git(pkg)
} else {
self.list_files_walk(pkg)
- };
-
- fn list_files_git(&self, pkg: &Package) -> CargoResult<Vec<Path>> {
- let cwd = pkg.get_manifest_path().dir_path();
- let mut cmd = process("git").cwd(cwd.clone());
- cmd = cmd.arg("ls-files").arg("-z");
-
- // Filter out all other packages with a filter directive
- for pkg in self.packages.iter().filter(|p| *p != pkg) {
- if cwd.is_ancestor_of(pkg.get_manifest_path()) {
- let filter = pkg.get_manifest_path().dir_path()
- .path_relative_from(&self.path).unwrap();
- cmd = cmd.arg("-x").arg(filter);
- }
+ });
+
+ let pats = pkg.get_manifest().get_exclude().iter().map(|p| {
+ Pattern::new(p.as_slice())
+ }).collect::<Vec<Pattern>>();
+
+ let root = pkg.get_manifest_path().dir_path();
+ Ok(candidates.move_iter().filter(|candidate| {
+ let candidate = candidate.path_relative_from(&root).unwrap();
+ !pats.iter().any(|p| p.matches_path(&candidate))
+ }).collect())
+ }
+
+ fn list_files_git(&self, pkg: &Package) -> CargoResult<Vec<Path>> {
+ let cwd = pkg.get_manifest_path().dir_path();
+ let mut cmd = process("git").cwd(cwd.clone());
+ cmd = cmd.arg("ls-files").arg("-z");
+
+ // Filter out all other packages with a filter directive
+ for pkg in self.packages.iter().filter(|p| *p != pkg) {
+ if cwd.is_ancestor_of(pkg.get_manifest_path()) {
+ let filter = pkg.get_manifest_path().dir_path()
+ .path_relative_from(&self.path).unwrap();
+ cmd = cmd.arg("-x").arg(filter);
}
+ }
- log!(5, "listing git files with: {}", cmd);
- let output = try!(cmd.arg(".").exec_with_output());
- let output = output.output.as_slice();
- Ok(output.split(|x| *x == 0).map(Path::new).collect())
+ log!(5, "listing git files with: {}", cmd);
+ let output = try!(cmd.arg(".").exec_with_output());
+ let output = output.output.as_slice();
+ Ok(output.split(|x| *x == 0).map(|p| cwd.join(p)).collect())
+ }
+
+ fn list_files_walk(&self, pkg: &Package) -> CargoResult<Vec<Path>> {
+ let mut ret = Vec::new();
+ for pkg in self.packages.iter().filter(|p| *p == pkg) {
+ let loc = pkg.get_manifest_path().dir_path();
+ try!(walk(&loc, &mut ret, true));
}
+ return Ok(ret);
- fn list_files_walk(&self, pkg: &Package) -> CargoResult<Vec<Path>> {
- let mut ret = Vec::new();
- for pkg in self.packages.iter().filter(|p| *p == pkg) {
- let loc = pkg.get_manifest_path().dir_path();
- try!(walk(&loc, &mut ret, true));
+ fn walk(path: &Path, ret: &mut Vec<Path>,
+ is_root: bool) -> CargoResult<()> {
+ if !path.is_dir() {
+ ret.push(path.clone());
+ return Ok(())
}
- return Ok(ret);
-
- fn walk(path: &Path, ret: &mut Vec<Path>,
- is_root: bool) -> CargoResult<()> {
- if !path.is_dir() {
- ret.push(path.clone());
- return Ok(())
- }
- // Don't recurse into any sub-packages that we have
- if !is_root && path.join("Cargo.toml").exists() { return Ok(()) }
- for dir in try!(fs::readdir(path)).iter() {
- match (is_root, dir.filename_str()) {
- (_, Some(".git")) |
- (true, Some("target")) |
- (true, Some("Cargo.lock")) => continue,
- _ => {}
- }
- try!(walk(dir, ret, false));
+ // Don't recurse into any sub-packages that we have
+ if !is_root && path.join("Cargo.toml").exists() { return Ok(()) }
+ for dir in try!(fs::readdir(path)).iter() {
+ match (is_root, dir.filename_str()) {
+ (_, Some(".git")) |
+ (true, Some("target")) |
+ (true, Some("Cargo.lock")) => continue,
+ _ => {}
}
- return Ok(())
+ try!(walk(dir, ret, false));
}
+ return Ok(())
}
}
}
test: Option<Vec<TomlTestTarget>>,
bench: Option<Vec<TomlTestTarget>>,
dependencies: Option<HashMap<String, TomlDependency>>,
- dev_dependencies: Option<HashMap<String, TomlDependency>>
+ dev_dependencies: Option<HashMap<String, TomlDependency>>,
}
#[deriving(Encodable,Decodable,PartialEq,Clone)]
pub version: String,
pub authors: Vec<String>,
build: Option<TomlBuildCommandsList>,
+ exclude: Option<Vec<String>>,
}
#[deriving(Encodable,Decodable,PartialEq,Clone,Show)]
Some(MultipleBuildCommands(ref cmd)) => cmd.clone(),
None => Vec::new()
};
+ let exclude = project.exclude.clone().unwrap_or(Vec::new());
let summary = Summary::new(&pkgid, deps.as_slice());
let mut manifest = Manifest::new(&summary,
&layout.root.join("target"),
&layout.root.join("doc"),
sources,
- build);
+ build,
+ exclude);
if used_deprecated_lib {
manifest.add_warning(format!("the [[lib]] section has been \
deprecated in favor of [lib]"));
-use std::io::{fs, TempDir};
+use std::io::{fs, TempDir, File};
use std::os;
use std::path;
use support::{ResultTest, project, execs, main_file, basic_bin_manifest};
-use support::{COMPILING, RUNNING, cargo_dir, ProjectBuilder, path2url};
+use support::{COMPILING, RUNNING, FRESH, cargo_dir, ProjectBuilder, path2url};
use hamcrest::{assert_that, existing_file};
+use support::paths::PathExt;
use cargo;
use cargo::util::{process, realpath};
.with_stderr("\
the [[lib]] section has been deprecated in favor of [lib]\n"));
})
+
+test!(freshness_ignores_excluded {
+ let foo = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.0"
+ authors = []
+ build = "true"
+ exclude = ["src/b*.rs"]
+ "#)
+ .file("src/lib.rs", "pub fn bar() -> int { 1 }");
+ foo.build();
+ foo.root().move_into_the_past().assert();
+
+ assert_that(foo.process(cargo_dir().join("cargo-build")),
+ execs().with_status(0)
+ .with_stdout(format!("\
+{compiling} foo v0.0.0 ({url})
+", compiling = COMPILING, url = foo.url())));
+
+ // Smoke test to make sure it doesn't compile again
+ println!("first pass");
+ assert_that(foo.process(cargo_dir().join("cargo-build")),
+ execs().with_status(0)
+ .with_stdout(format!("\
+{fresh} foo v0.0.0 ({url})
+", fresh = FRESH, url = foo.url())));
+
+ // Modify an ignored file and make sure we don't rebuild
+ println!("second pass");
+ File::create(&foo.root().join("src/bar.rs")).assert();
+ assert_that(foo.process(cargo_dir().join("cargo-build")),
+ execs().with_status(0)
+ .with_stdout(format!("\
+{fresh} foo v0.0.0 ({url})
+", fresh = FRESH, url = foo.url())));
+})